package ager

import (
	"image"
	"fmt"
	"code.google.com/p/go.image/tiff"
	"os"
	"math/rand"
	"image/color"
)

func Aging(img image.Image, histData []int, probability int, name string, set bool, col uint8) {
	file, err := os.Create(name)
	if err != nil {
		fmt.Println(err)
	}

	// new blank image is created
	newImage := image.NewGray(image.Rect(
		img.Bounds().Min.X, img.Bounds().Min.Y,
		img.Bounds().Max.X, img.Bounds().Max.Y))

	for width := img.Bounds().Min.X; width < img.Bounds().Max.X; width++ {
		for height := img.Bounds().Min.Y; height < img.Bounds().Max.Y; height++ {
			rnd1 := rand.Intn(100)
			// does this pixel get changed?
			if rnd1 < probability {
				if !set {
					// what value should it have according to the distribution?
					rnd2 := rand.Intn(histData[len(histData) - 1])
					col = uint8(binarySearch(histData,
						func(x int) bool {
							return x >= rnd2
						}))
				}
				newImage.SetGray(width, height, color.Gray{col})
				// or is it just copied?
			} else {
				newImage.SetGray(width, height, img.At(width, height).(color.Gray))
			}
		}
	}

	tiff.Encode(file, newImage, nil)
	file.Close()

}

func binarySearch(arr []int, f func(int) bool) int {
	lo, hi := 0, len(arr)
	bestSoFar := -1

	for lo <= hi {
		x := (lo + hi) / 2
		if f(arr[x]) {
			// we found a potential minimum x, but we should still check to see
			// if any smaller ones work
			bestSoFar = x
			hi = x-1
		} else {
			// the predicate is false, so we need to go right to find true values
			lo = x+1
		}
	}
	return bestSoFar
}

